package impl

import (
	"errors"
	"fmt"
	"github.com/gorilla/websocket"
	"sync"
)

type Connection struct {
	wsConn *websocket.Conn
	inChan chan []byte //wsConn 输入消息队列
	outChan chan []byte //wsConn 输出消息队列
	closeChan chan struct{}
	once *sync.Once
}


//初始化封装的websocket连接
func NewConnection(wsConn *websocket.Conn) *Connection {

	conn:= &Connection{
		wsConn:  wsConn,
		inChan:  make(chan []byte,1000),
		outChan: make(chan []byte,1000),
		closeChan:make(chan struct{}),
		once:new(sync.Once),
	}

	go conn.ReadLoop()
	go conn.WriteLoop()

	return conn
}

//从输入消息队列中读消息
func (this *Connection)ReadMessage() (data []byte,err error) {
	select {
	case data=<-this.inChan:
	case <-this.closeChan:
		err=errors.New("connection is close")
	}
	return
}

//从输出消息队列中读取消息
func (this *Connection)WriteMessage(data []byte)(err error) {

	select {
	case this.outChan<-data:
	case <-this.closeChan:
		err=errors.New("connection is close")
	}
	return
}


//关闭wsConn连接
func (this *Connection)Close() error {
	if err:= this.wsConn.Close();err!= nil {
		return err
	}

	this.once.Do(func() {
		close(this.closeChan)
	})

	return nil
}


//读携程,不停的将wsConn的消息读到in队列中
func (this *Connection)ReadLoop() (err error) {
	var data []byte
	defer this.Close()
	for {
		if _,data,err=this.wsConn.ReadMessage();err!= nil {
			fmt.Println(err)
			return
		}else{

			select {
			case this.inChan<-data:
			case <-this.closeChan:
				return
			}

		}
	}
}

//写携程,不停将outChan中的消息写入到wsConn中
func (this *Connection)WriteLoop() (err error) {
	var data []byte

	defer this.Close()
	for {
		select {
		case data=<-this.outChan:
		case <-this.closeChan:
			return
		}

		if err=this.wsConn.WriteMessage(websocket.TextMessage,data);err!= nil {
			fmt.Println(err)
			return
		}
	}
}

